/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package cas;

import remixlab.proscene.*;
import processing.core.*;

/**
 *
 * @author DAVINCI
 */
public class CAS extends PApplet {

    InteractiveFrame pControl1;
    InteractiveFrame pControl2;
    InteractiveFrame pControl3;
    InteractiveFrame pControl4;

    float x1;


    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        PApplet.main(new String[]{"cas.CAS"});
    }
    Scene scene;
    public int method = 0;
    public String rep;
    private static double hermiteMatrix[][] = {
        {2, -2, 1, 1},
        {-3, 3, -2, -1},
        {0, 0, 1, 0},
        {1, 0, 0, 0}
    };

    private static double bezierMatrix[][] = {
		{-1, 3,-3, 1},
		{ 3,-6, 3, 0},
		{-3, 3, 0, 0},
		{ 1, 0, 0, 0},
	};
    Matrix Mb = new Matrix(bezierMatrix);
    Matrix Mh = new Matrix(hermiteMatrix);
    double P1[] = {5, 20, 60};
    double P4[] = {5, 70, 60};
    double R1[] = {79, 76, 87};
    double R4[] = {50, 30, 60};
    double geom[][] = {
        P1,
        P4,
        {R1[0] - P1[0], R1[1] - P1[1], R1[2] - P1[2]},
        {P4[0] - R4[0], P4[1] - R4[1], P4[2] - R4[2]}
    };


    Matrix Gh = new Matrix(geom);
    Matrix MG = Mh.times(Gh);

    public void setup() {
        size(640, 360, P3D);

        scene = new Scene(this);
        scene.setGridIsDrawn(false);
        scene.setShortcut('f', Scene.KeyboardAction.DRAW_FRAME_SELECTION_HINT);
        pControl1 = new InteractiveFrame(scene);
        pControl1.setPosition(20, 40, 60);
        pControl2 = new InteractiveFrame(scene);
        pControl2.setPosition(100, 40, 60);
        pControl3 = new InteractiveFrame(scene);
        pControl3.setPosition(40, 40, 60);
        pControl4 = new InteractiveFrame(scene);
        pControl4.setPosition(60, 40, 60);
//        R1[0]=R1[0] - P1[0];
//            R1[1]=R1[1] - P1[1];
//            R1[2]=R1[2] - P1[2];
//            R4[0]=P4[0] - R4[0];
//            R4[1]=P4[1] - R4[1];
//            R4[2]=P4[2] - R4[2];

//        scene.showAll();

//        addBox();


    }

//    void addBox() {
//        Box box = new Box(scene);
//        box.setSize(20, 20, 20);
//        box.setColor(color(0, 0, 255));
//
//    }

    public void draw() {

        P1[0] = pControl1.position().x;
        P1[1] = pControl1.position().y;
        P1[2] = pControl1.position().z;

        P4[0] = pControl2.position().x;
        P4[1] = pControl2.position().y;
        P4[2] = pControl2.position().z;

        R1[0] = pControl3.position().x;
        R1[1] = pControl3.position().y;
        R1[2] = pControl3.position().z;

        R4[0] = pControl4.position().x;
        R4[1] = pControl4.position().y;
        R4[2] = pControl4.position().z;

        if (method==0)
        curva();
        if (method==1)
      curvaB();
    }

    public void keyPressed() {
        if ((key == 'x') || (key == 'X')) {
            println(this.pControl1.position());

        }
//  crearPoligonos();
        if ((key == 'm') || (key == 'M')) {
//            addBox();
        }
        if ((key == 'H') || (key == 'h')) {
            method = 0;
        }
        if ((key == 'B') || (key == 'b')) {
            method = 1;
        }
        if ((key == 'S') || (key == 's')) {
            method = 10;
        }
        if ((key == 'f') || (key == 'F')) {
            method = 11;
        }
        if ((key == 'Q') || (key == 'q')) {
            method = 16;
        }
        if ((key == '1')) {
            rep = "explicita";
        }
        if ((key == '2')) {
            rep = "vertices";
        }

    }

    public double[][] generarT(double i) {
        double T[][] = {
            {Math.pow(i, 3), Math.pow(i, 2), i, 1}
        };

        return T;
    }

    public double[][] generarTb(double i) {
        double T[][] = {
            {(1-i)*(1-i)*(1-i),3*i*((1-i)*(1-i)),(3*(i*i))*(1-i),i*i*i}
        };

        return T;
    }

    public void curva() {
        
        float t = 0;
        int n = 400;
        float delta = (float)1.0 / n;
//        double T[][] = {
//            {0, 0, 0, 1}
//        };


//        Matrix Tt = new Matrix(T);
//        Matrix Qt = Tt.times(MG);

//        double XYZ[][] = Qt.getData();
        double H0U;
        double H1U;
        double H2U;
        double H3U;
        double[] Pk = new double[3];
        double[] Pk1 = new double[3];
        double[] Dk = new double[3];
        double[] Dk1 = new double[3];
        double[] xyz = new double[3];
        stroke(255);
        noFill();
        beginShape();
        for (int i = 0; i <=n; i++) {
            H0U=2*(Math.pow(t, 3))-(3*Math.pow(t, 2))+1;
            H1U=(-2*(Math.pow(t, 3)))+(3*Math.pow(t, 2));
            H2U=((Math.pow(t, 3)))-(2*Math.pow(t, 2))+t;
            H3U=((Math.pow(t, 3)))-(Math.pow(t, 2));
            Pk[0]=P1[0]*H0U;
            Pk[1]=P1[1]*H0U;
            Pk[2]=P1[2]*H0U;
            Pk1[0]=P4[0]*H1U;
            Pk1[1]=P4[1]*H1U;
            Pk1[2]=P4[2]*H1U;
            Dk[0]=R1[0]*H2U;
            Dk[1]=R1[1]*H2U;
            Dk[2]=R1[2]*H2U;
            Dk1[0]=R4[0]*H3U;
            Dk1[1]=R4[1]*H3U;
            Dk1[2]=R4[2]*H3U;
            xyz[0]= Pk[0] + Pk1[0] + Dk[0] + Dk1[0];
            xyz[1]= Pk[1] + Pk1[1] + Dk[1] + Dk1[1];
            xyz[2]= Pk[2] + Pk1[2] + Dk[2] + Dk1[2];

            vertex((int)xyz[0],(int)xyz[1],(int)xyz[2]);

            t = t + delta;
//            Tt = new Matrix(generarT(t));
//            Qt = Tt.times(MG);
//            t = t + delta;
//            XYZ = Qt.getData();
//            vertex((int) Math.floor(XYZ[0][0]), (int) Math.floor(XYZ[0][1]), (int) Math.floor(XYZ[0][2]));

        }
        endShape();
        stroke(0,255,0);
//         translate(5, 20, 60);
//            sphere((float) 0.4);
//            translate(-5, -20, -60);
//            translate(5, 70, 60);
//            sphere((float) 0.4);
//            translate(-5, -70, -60);
//            translate(79, 76, 87);
//            sphere((float) 0.4);
//            translate(-79, -76, -87);
//            translate(50, 30, 60);
//            sphere((float) 0.4);
//            translate(-50, -30, -60);

    }

    private void curvaB() {
        float t = 0;
        int n = 400;
        float delta = (float)1.0 / n;
//        double T[][] = {
//            {0, 0, 0, 1}
//        };


//        Matrix Tt = new Matrix(T);
//        Matrix Qt = Tt.times(MG);

//        double XYZ[][] = Qt.getData();
        double H0U;
        double H1U;
        double H2U;
        double H3U;
        double[] Pk = new double[3];
        double[] Pk1 = new double[3];
        double[] Dk = new double[3];
        double[] Dk1 = new double[3];
        double[] xyz = new double[3];
        stroke(255);
        noFill();
        beginShape();
        for (int i = 0; i <=n; i++) {
            H0U=Math.pow((1-t),3);
            H1U=3*t*Math.pow((1-t),2);
            H2U=3*Math.pow(t,2)*(1-t);
            H3U=Math.pow(t, 3);
            Pk[0]=P1[0]*H0U;
            Pk[1]=P1[1]*H0U;
            Pk[2]=P1[2]*H0U;
            Pk1[0]=P4[0]*H1U;
            Pk1[1]=P4[1]*H1U;
            Pk1[2]=P4[2]*H1U;
            Dk[0]=R1[0]*H2U;
            Dk[1]=R1[1]*H2U;
            Dk[2]=R1[2]*H2U;
            Dk1[0]=R4[0]*H3U;
            Dk1[1]=R4[1]*H3U;
            Dk1[2]=R4[2]*H3U;
            xyz[0]= Pk[0] + Pk1[0] + Dk[0] + Dk1[0];
            xyz[1]= Pk[1] + Pk1[1] + Dk[1] + Dk1[1];
            xyz[2]= Pk[2] + Pk1[2] + Dk[2] + Dk1[2];

            vertex((int)xyz[0],(int)xyz[1],(int)xyz[2]);

            t = t + delta;
//            Tt = new Matrix(generarT(t));
//            Qt = Tt.times(MG);
//            t = t + delta;
//            XYZ = Qt.getData();
//            vertex((int) Math.floor(XYZ[0][0]), (int) Math.floor(XYZ[0][1]), (int) Math.floor(XYZ[0][2]));

        }
        endShape();
        stroke(0,255,0);
    }
}

//class Box extends PApplet {
//
//    InteractiveFrame iFrame;
//    Scene scene;
//    float w, h, d;
//    int c;
//
//    Box(Scene a) {
//        this.scene = a;
//        iFrame = new InteractiveFrame(scene);
//        setSize();
//        setColor();
//        setPosition();
//    }
//
//    // don't draw local axis
//    public void draw() {
//        draw(false);
//    }
//
//    public void draw(boolean drawAxis) {
//        pushMatrix();
//        pushStyle();
//        // Multiply matrix to get in the frame coordinate system.
//        // scene.parent.applyMatrix(iFrame.matrix()) is handy but inefficient
//        iFrame.applyTransformation(); //optimum
//        if (drawAxis) {
//            scene.drawAxis(max(w, h, d) * 1.3f);
//        }
//        noStroke();
//        if (iFrame.grabsMouse()) {
//            fill(255, 0, 0);
//        } else {
//            fill(getColor());
//        }
//        //Draw a box
//        box(w, h, d);
//        popStyle();
//        popMatrix();
//    }
//
//    // sets size randomly
//    public void setSize() {
//        w = random(10, 40);
//        h = random(10, 40);
//        d = random(10, 40);
//    }
//
//    public void setSize(float myW, float myH, float myD) {
//        w = myW;
//        h = myH;
//        d = myD;
//    }
//
//    public int getColor() {
//        return c;
//    }
//
//    // sets color randomly
//    public void setColor() {
//        c = color(random(0, 255), random(0, 255), random(0, 255));
//    }
//
//    public void setColor(int myC) {
//        c = myC;
//    }
//
//    public PVector getPosition() {
//        return iFrame.position();
//    }
//
//    // sets position randomly
//    public void setPosition() {
//        float low = -100;
//        float high = 100;
//        iFrame.setPosition(new PVector(random(low, high), random(low, high), random(low, high)));
//    }
//
//    public void setPosition(PVector pos) {
//        iFrame.setPosition(pos);
//    }
//
//    public Quaternion getOrientation() {
//        return iFrame.orientation();
//    }
//
//    public void setOrientation(PVector v) {
//        PVector to = PVector.sub(v, iFrame.position());
//        iFrame.setOrientation(new Quaternion(new PVector(0, 1, 0), to));
//    }
//}
